using Constants;
using ELF.Consul;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Validation.AspNetCore;
using System.Text;
using static OpenIddict.Abstractions.OpenIddictConstants;

namespace ELF.Modules;

[DependsOn(typeof(ElfConsulModule))]
[DependsOn(typeof(ElfdddWebApiModule))]
[DependsOn(typeof(ApplicationModule))]
[DependsOn(typeof(InfrastructureModule))]
//[DependsOn(typeof(ELFDDDDataModule))]
public class IdentityApiModule : BaseModule
{
    public override async Task ConfigureServicesAsync(IHostApplicationBuilder builder)
    {
        builder.Services.AddExceptionHandler<CustomExceptionHandler>();
        builder.Services.Configure<ApiBehaviorOptions>(options =>
            options.SuppressModelStateInvalidFilter = true);
        ConfigureAuthentication(builder.Services, builder.Configuration);
        //builder.AddDefaultCors();
        builder.Services.AddOpenApi();
        await Task.CompletedTask;
    }

    public override async Task InitializeAsync(IApplicationBuilder app)
    {
        //app.UseDefaultCors();
        if ((app is IEndpointRouteBuilder endpoint))
        {
            endpoint.MapOpenApi();
        }
        
        await Task.CompletedTask;
    }

    private static void ConfigureAuthentication(IServiceCollection services, IConfiguration configuration)
    {
        var encryptionKeyText = configuration["OpenIddict:EncryptionKey"];
        if (string.IsNullOrEmpty(encryptionKeyText))
        {
            throw new ArgumentNullException("OpenIddict:EncryptionKey", "������֤����Կ��");
        }

        // ����OpenIddict
        services.AddOpenIddict()
            .AddServer(options =>
            {
                #region ��Ȩ�˵�
                options.SetTokenEndpointUris("/connect/token")
                       .SetAuthorizationEndpointUris("/connect/authorize");
                #endregion

                #region ģʽ
                options.AllowAuthorizationCodeFlow();
                options.AllowPasswordFlow();
                options.AllowClientCredentialsFlow();
                options.AllowRefreshTokenFlow();
                options.AcceptAnonymousClients();
                #endregion
                options.RegisterScopes(Scopes.OfflineAccess, "api");

                #region ǩ����Կ
                options.AddDevelopmentEncryptionCertificate()
                    .AddDevelopmentSigningCertificate();
                options.DisableAccessTokenEncryption();
                options.AddEncryptionKey(new SymmetricSecurityKey(Convert.FromBase64String("na8LnVekSu5b3fgdUhyo+KuLTMVGYLtgHrTTpKCB5VY=")));
                #endregion

                #region ������Ҫ������
                options.SetAccessTokenLifetime(TimeSpan.FromHours(12));
                options.SetRefreshTokenLifetime(TimeSpan.FromDays(3));
                #endregion

                options.UseAspNetCore()
                .EnableTokenEndpointPassthrough()
                .DisableTransportSecurityRequirement();
            });

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = configuration["GatewayJwt:Issuer"],
                        ValidAudience = configuration["GatewayJwt:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(
                            Encoding.UTF8.GetBytes(configuration["GatewayJwt:SecretKey"]!))
                    };
                });

        //services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
        //services.AddAuthorization(options =>
        //{
        //    options.AddPolicy(PermissionConstants.PolicyNames, policy =>
        //        policy.Requirements.Add(new PermissionRequirement()));
        //});
    }
}
